[IA64] add parameter check to ioremap hypercall
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Wed, 17 May 2006 21:53:14 +0000 (15:53 -0600)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Wed, 17 May 2006 21:53:14 +0000 (15:53 -0600)
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
xen/arch/ia64/xen/domain.c

index b9c0f3076bf3546da5cbe9981176f36f10a59d95..cb32d01ff9f564f1b51418aa1090b306fcddf69e 100644 (file)
@@ -837,6 +837,56 @@ assign_domain_same_page(struct domain *d,
     }
 }
 
+static int
+efi_mmio(unsigned long physaddr, unsigned long size)
+{
+    void *efi_map_start, *efi_map_end;
+    u64 efi_desc_size;
+    void* p;
+
+    efi_map_start = __va(ia64_boot_param->efi_memmap);
+    efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+    efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+    for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+        efi_memory_desc_t* md = (efi_memory_desc_t *)p;
+        unsigned long start = md->phys_addr;
+        unsigned long end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+        
+        if (start <= physaddr && physaddr < end) {
+            if ((physaddr + size) > end) {
+                DPRINTK("%s:%d physaddr 0x%lx size = 0x%lx\n",
+                        __func__, __LINE__, physaddr, size);
+                return 0;
+            }
+
+            // for io space
+            if (md->type == EFI_MEMORY_MAPPED_IO ||
+                md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) {
+                return 1;
+            }
+
+            // for runtime
+            // see efi_enter_virtual_mode(void)
+            // in linux/arch/ia64/kernel/efi.c
+            if ((md->attribute & EFI_MEMORY_RUNTIME) &&
+                !(md->attribute & EFI_MEMORY_WB)) {
+                return 1;
+            }
+
+            DPRINTK("%s:%d physaddr 0x%lx size = 0x%lx\n",
+                    __func__, __LINE__, physaddr, size);
+            return 0;
+        }
+
+        if (physaddr < start) {
+            break;
+        }
+    }
+
+    return 1;
+}
+
 unsigned long
 assign_domain_mmio_page(struct domain *d,
                         unsigned long mpaddr, unsigned long size)
@@ -845,6 +895,11 @@ assign_domain_mmio_page(struct domain *d,
         DPRINTK("%s: domain %p mpaddr 0x%lx size = 0x%lx\n",
                 __func__, d, mpaddr, size);
     }
+    if (!efi_mmio(mpaddr, size)) {
+        DPRINTK("%s:%d domain %p mpaddr 0x%lx size = 0x%lx\n",
+                __func__, __LINE__, d, mpaddr, size);
+        return -EINVAL;
+    }
     assign_domain_same_page(d, mpaddr, size);
     return mpaddr;
 }